
import ast
import os
import threading
import time
import uuid
from typing import Any, List
from aioredis import Redis
from redis import Redis
from fastapi import UploadFile
from sqlalchemy import delete, select, update, desc, func, text, or_, and_
from case.execlHandle import ExcelHandle
from initialization.crudInit import find_pojos, delete_pojo, update_pojo, insert_pojo
from initialization.dbInit import get_async_session
from initialization.redisInit import get_sync_redis
from model.entitys import Case, CaseGroup, ScheduledTask, Execut, get_sync_db, Status
from monitor.data_storage.excel_handle import write_in
from service import caseService
from service.apiService import ApiService
from service.caseService import run_case
from utils import business
from utils.decorator import transaction_decorator, transaction_decorator_sync
from variable import dependent_data, file_thread_pool, write_thread_pool, command_thread_pool

@transaction_decorator
async def add_case_group(session, case_group) -> Any:
    case_group["id"] = uuid.uuid1().__str__()
    await insert_pojo(session, CaseGroup, case_group)

@transaction_decorator
async def update_case_group(session, case_group) -> Any:
    await update_pojo(session, CaseGroup, case_group)

async def find_case_group(session, case_group) -> Any:
    query = select(CaseGroup)

    if case_group.id != "":
        query = query.where(CaseGroup.id.like("%" + case_group.id + "%"))

    if case_group.title != "":
        query = query.where(CaseGroup.title.like("%" + case_group.title + "%"))

    if case_group.system_name != "":
        query = query.where(CaseGroup.system_name.like("%" + case_group.system_name + "%"))

    if case_group.modular_name != "":
        query = query.where(CaseGroup.modular_name.like("%" + case_group.modular_name + "%"))

    if case_group.start_time != "":
        query = query.where(CaseGroup.created_at >= case_group.start_time)

    if case_group.end_time != "":
        query = query.where(CaseGroup.created_at <= case_group.end_time)

    if case_group.page_no <= 0:
        return {"message": "page_no必须大于0", "code": 400, "data": None}

    if case_group.page_size <= 0:
        return {"message": "page_size必须大于0", "code": 400, "data": None}

    case_group_list = await find_pojos(session, CaseGroup, query, case_group)

    await session.close()

    return {"message": "查询成功", "code": 200, "data": case_group_list}

async def judge_existence_case(session, case_group_id):
    case_list = (await session.execute(
        select(Case).where(Case.case_group_id == case_group_id))).scalars().all()

    if len(case_list) > 0:
        await session.close()

        return {"message": "该用例组下面还存在用例", "code": 400, "data": None}

@transaction_decorator
async def delete_case_group(session, case_group_id) -> Any:
    await delete_pojo(session, CaseGroup, case_group_id)

def judge_running(redis: Redis, gain_id):
    if isinstance(gain_id, List):
        business.clear_running_case(redis, gain_id)

    else:
        if redis.exists(gain_id):
            return {"message": "该用例组正在执行中,请稍后再试", "code": 400, "data": None}
        else:
            redis.set(gain_id, Execut.ACTIVE)

def batch_run_case(api, gain_id):
    session = get_sync_db()
    redis = get_sync_redis()

    for case_group_id in gain_id:
        run_case(api, case_group_id, session=session, redis=redis)

@transaction_decorator
async def add_case(session, case) -> Any:
    case["id"] = uuid.uuid1().__str__()
    await insert_pojo(session, Case, case)

    case_group = (await session.execute(select(CaseGroup).where(CaseGroup.id == case.case_group_id))).scalars().first()

    await session.execute(update(CaseGroup).where(CaseGroup.id == case_group.id)).valuse({
        "case_number": case_group.case_number + 1
    })

@transaction_decorator
async def update_case(session, case) -> Any:
    await update_pojo(session, Case, case)

async def find_case(session, case) -> Any:
    query = select(Case)

    if case.id != "":
        query = query.where(Case.id.like("%" + case.id + "%"))

    if case.title != "":
        query = query.where(Case.title.like("%" + case.title + "%"))

    if case.case_group_id != "":
        query = query.where(Case.case_group_id.like("%" + case.case_group_id + "%"))

    if case.enable != "":
        query = query.where(Case.enable == case.enable)

    if case.method != "":
        query = query.where(Case.method.like("%" + case.method + "%"))

    if case.url_or_sql != "":
        query = query.where(Case.url_or_sql.like("%" + case.url_or_sql + "%"))

    if case.param_type != "":
        query = query.where(Case.param_type.like("%" + case.param_type + "%"))

    if case.whether != "":
        query = query.where(Case.whether == case.whether)

    if case.start_time != "":
        query = query.where(Case.created_at >= case.start_time)

    if case.end_time != "":
        query = query.where(Case.created_at <= case.end_time)

    if case.page_no <= 0:
        return {"message": "page_no必须大于0", "code": 400, "data": None}

    if case.page_size <= 0:
        return {"message": "page_size必须大于0", "code": 400, "data": None}

    case_list = await find_pojos(session, Case, query, case)

    await session.close()

    return {"message": "查询成功", "code": 200, "data": case_list}

@transaction_decorator
async def delete_case(session, case_id) -> Any:
    await delete_pojo(session, Case, case_id)

    case_group = (await session.execute(
        select(CaseGroup).join(Case, Case.case_group_id == CaseGroup.id).where(Case.id == case_id))).scalars().first()

    await session.execute(update(CaseGroup).where(CaseGroup.id == case_group.id)).valuse({
        "case_number": case_group.case_number - 1
    })

def add_task(st):
# async def add_task(st):
    execution_info = ast.literal_eval(st["execution_info"])   # {"trigger":"interval","hours":2,"jitter":120}   {"trigger":"cron","month":"6-8,11-12", "day":"3rd fri", "hour":"0-3", "minute":45}
    if st["is_cmd"]:
        dependent_data["ground_sched"].add_job(command_line_execute, **execution_info, id=st["id"],
                                               args=[st["command"]])
    else:
        try:
            group_info = ast.literal_eval(st["group_info"])
        except Exception:
            group_info = st["group_info"]

        if st["is_batch"] == "True":
            for gi in group_info:
                if dependent_data["ground_sched"].get_job(gi):
                    continue
                else:
                    dependent_data["ground_sched"].add_job(caseService.run_case, **execution_info, id=st["id"],
                                                           args=[ApiService(), gi, True])
        else:
            if dependent_data["ground_sched"].get_job(group_info) is None:
                dependent_data["ground_sched"].add_job(caseService.run_case, **execution_info, id=st["id"],
                                                args=[ApiService(), group_info, True])

        # if st["is_group"] == "True":
        #     for gi in group_info:
        #         if dependent_data["sched"].get_job(gi):
        #             continue
        #         else:
        #             dependent_data["sched"].add_job(caseService.run_case, **execution_info, id=st["id"],
        #                                                    args=[ApiService(), gi, True])
        # else:
        #     if dependent_data["sched"].get_job(group_info) is None:
        #         dependent_data["sched"].add_job(caseService.run_case, **execution_info, id=st["id"],
        #                                         args=[ApiService(), group_info, True])

@transaction_decorator_sync
def add_sched(session, afst):
# @transaction_decorator
# async def add_sched(session, afst):
    afst["id"] = uuid.uuid1().__str__()
    afst["enable"] = Status.VALID
    session.add(ScheduledTask(**afst))
    # await insert_pojo(session, ScheduledTask, afst)

    add_task(afst)
    # await add_task(afst)

@transaction_decorator_sync
def delete_sched(session, st_id):
# @transaction_decorator
# async def delete_sched(session, st_id):
    session.query(ScheduledTask).filter(ScheduledTask.id == st_id).delete()
    # await delete_pojo(session, ScheduledTask, st_id)

    dependent_data["ground_sched"].remove_job(st_id)
    # dependent_data["sched"].remove_job(st_id)

@transaction_decorator_sync
def update_sched(session, afst):
# @transaction_decorator
# async def update_sched(session, afst):
    afst["enable"] = Status.VALID
    session.query(ScheduledTask).filter(ScheduledTask.id == afst["id"]).update(**afst)
    # await update_pojo(session, ScheduledTask, afst)

    dependent_data["ground_sched"].remove_job(afst.id)
    # dependent_data["sched"].remove_job(afst.id)

    add_task(afst)
    # await add_task(afst)

async def find_sched(session, afst):
    query = select(ScheduledTask)

    if afst.id != "":
        query = query.where(ScheduledTask.id.like("%" + afst.id + "%"))

    if afst.title != "":
        query = query.where(ScheduledTask.title.like("%" + afst.title + "%"))

    if afst.enable != "":
        query = query.where(ScheduledTask.enable == afst.enable)

    if afst.execution_info != "":
        query = query.where(ScheduledTask.execution_info.like("%" + afst.execution_info + "%"))

    if afst.group_info != "":
        query = query.where(ScheduledTask.group_info.like("%" + afst.group_info + "%"))

    if afst.start_time != "":
        query = query.where(ScheduledTask.created_at >= afst.start_time)

    if afst.end_time != "":
        query = query.where(ScheduledTask.created_at <= afst.end_time)

    if afst.page_no <= 0:
        return {"message": "page_no必须大于0", "code": 400, "data": None}

    if afst.page_size <= 0:
        return {"message": "page_size必须大于0", "code": 400, "data": None}

    scheduled_task_list = await find_pojos(session, ScheduledTask, query, afst)

    await session.close()

    return {"message": "查询成功", "code": 200, "data": scheduled_task_list}

@transaction_decorator_sync
def start_pause_sched(session, afst):
# @transaction_decorator
# async def start_pause_sched(session, afst):
    session.query(ScheduledTask).filter(ScheduledTask.id == afst.id).update({
        "enable": afst.enable
    })
    # await session.execute(update(ScheduledTask).where(ScheduledTask.id == afst.id)).valuse({
    #     "enable": afst.enable
    # })

    if afst.enable == 0:
        dependent_data["ground_sched"].pause_job(afst.id)
        # dependent_data["sched"].pause_job(afst.id)
    else:
        dependent_data["ground_sched"].resume_job(afst.id)
        # dependent_data["sched"].resume_job(afst.id)

def upload_cases(files: List[UploadFile]):
    for file in files:
        content = file.file.read()
        with open('./documents/' + file.filename, 'wb') as f:
            f.write(content)

        db = get_sync_db()
        file_thread_pool.submit(ExcelHandle("documents/" + file.filename).get_data, "w", db)
        # threading.Thread(target=ExcelHandle("documents/" + file.filename).get_data, args=("w", db)).start()

    return {"message": "导入成功", "code": 200, "data": None}

def command_line_execute(cmd: str):
    os.system(cmd)

def app_pressure(redis: Redis, info: dict):
    redis.set(info["package"], Execut.ACTIVE)

    os.system(info["connect"])

    command_thread_pool.submit(command_line_execute, info["cmd"])

    write_thread_pool.submit(write_in, info["package"], info["duration"])

def monkey_command(command: dict):
    os.system(command["connect"])

    command_thread_pool.submit(command_line_execute, command["monkey"])

    write_thread_pool.submit(command_line_execute, command["cmd"])




































